#-*- encoding:utf-8 -*-
"""
显示项：App Version

每一列的判断条件：

In Production:  app version的Production Status = In Production 并且 还没有创建Dev QA Request
Pending Dev-QA:  Dev-QA Status= Pending
In Dev-QA: Dev-QA Status= In Progress
Pending Release QA：Release QA Status = Pending
In Release QA：Release QA Status = In Progress
QA Cleared: Release QA Status = Cleared 并且 还没有创建对应的Submission Request 或者Submission Request Validation = Pending
Packaging：Release QA Status = Cleared 并且 已经创建 Submission Request 并且 Submission Request Validation= Valid
Submitted:  Submission Request中, Submission Status=Submitted 并且Review Status=Pending Review
Pending Release:   （PS上） Review Status = Pending Release
Rejected: （PS上）Rejection 里面有关联的Issue并且 Status = Open


所有要在开发中的app version，都应该要出现在这个Kanban Board里面，不应该有在开发中的app version但是没有显示在这个Kanban Board上的情况。

同一个app version应该只出现在一列里面，不可能同时出现在两列里面。

不记录Release和Release以后的流程。App version进入到 Review Status = Release的状态以后，就认为这个app version已经结束了，从这个Kanban Board上消失。

暂时不记录被Cancel和On Hold的App version。任何一个App Version在任意时候，Production Status = Cancelled或者On Hold。 该app version自动从Kanban Board消失，不再显示。



所有的widget都从最左边流动到最右边。默认一定是从最左边第一列In Production开始，一旦满足右边一列的条件，就往右流动一列，依次逐列往右挪动。

可能出现往回挪一列或者反复移动的情况。 （例如：QA状态改为In Progress之后又改回Pending）
"""

from app_info.models import *
import urllib2
import json
from django.conf import settings
from django.db.models import Q
from datetime import date,datetime,timedelta

def get_global():
    return globals()

def get_companys(request):
    com_codes=[]
    for g in request.user.groups.all():
        com_codes.append(g.companygroup.company.code)
    return {'companys':com_codes}

def get_week_and_days():
    today=datetime.today().date()
    y,w,d=today.isocalendar() 
    end=today.strftime('%b %d')
    start=get_last_sat().strftime('%b %d')
    return {'week':w,'start':start,'end':end,'year':y}

def get_kanban_data(user,company,store):
    #if isinstance(company,(str,unicode)):
        #company=Company.objects.get(code=company)
    if store=='app_store':
        app_store=AppStore(user, company)
        apple=app_store.get_data()
        return {'app_store':apple}
    elif store=='gp_store':
        gp_store=GpStore(user,company)
        google=gp_store.get_data()
        return {'gp_store':google}
    elif store=='amazon_store':
        amazon_store=AmazonStore(user, company)
        z=amazon_store.get_data()
        return {'amazon_store':z}

def ver_to_dict(version):
    app=version.app
    if version.prd_team:
        team=version.prd_team.name
    else:
        team=''
    return {'appcode':app.prj_code,
            'team':team,
            'version':version.code}  

class Store(object):
    """
    APP_STORE = (
    ('iTunes App Store', u'iTunes App Store'),
    ('Google Play', u'Google Play'),
    ('Amazon App Store', u'Amazon App Store'),
)


    """
    def __init__(self,user,company):
        self.store=None
        self.company=company
        self.include=['in_productions','pending_dev_qa','in_dev_qa','dev_cleared','pending_rel_qa',
                      'in_rel_qa','rel_cleared','queued','submitted','released']
     
    def get_data(self):
        dc={}
        for k in dir(self):
            name=k.lstrip('get_')
            if k.startswith('get_') and name in self.include:
                dc[name]=getattr(self,k)()
        return dc   
       
    def get_in_productions(self):
        """
        In Production:  app version的Production Status = In Production 并且 还没有创建Dev QA Request
        """
        out=[]
        for version in AppVersion.objects.filter(status='I',app__app_store=self.store,app__company=self.company):
            if version.app.devqainfo_set.filter(version=version.code).count()>=1:
                continue
            else:
                out.append(version)
        return out 
    
    def get_pending_dev_qa(self):
        """
        Pending Dev-QA:  Dev-QA Status= Pending
        """
        out=[]
        for dev in DevQAInfo.objects.filter(status='P',app__app_store=self.store,app__company=self.company):
            version=dev_to_version(dev)
            out.append(version)
        return out 
    
    def get_in_dev_qa(self):
        """
        In Dev-QA: Dev-QA Status= In Progress
        """
        out=[]
        for dev in DevQAInfo.objects.filter(status='I',app__app_store=self.store,app__company=self.company):
            version=dev_to_version(dev)
            out.append(version)
        return out
    
    def get_dev_cleared(self):
        """
        ('D', 'Cleared'),
        """
        out=[]
        for dev in DevQAInfo.objects.filter(status='D',app__app_store=self.store,app__company=self.company):
            version=dev_to_version(dev)
            out.append(version)
        return out        
    
    def get_pending_rel_qa(self):
        """
        Pending Release QA：Release QA Status = Pending
        """
        out=[]
        for rel in ReleaseQAInfo.objects.filter(status='P',dev_qa__app__app_store=self.store,dev_qa__app__company=self.company):
            dev =rel.dev_qa
            version=dev_to_version(dev)
            out.append(version)
        return out
    
    def get_in_rel_qa(self):
        """
        In Release QA：Release QA Status = In Progress
        """
        out=[]
        for rel in ReleaseQAInfo.objects.filter(status='I',dev_qa__app__app_store=self.store,dev_qa__app__company=self.company):
            dev=rel.dev_qa
            version=dev_to_version(dev)
            out.append(version)
        return out
    
    def get_rel_cleared(self):
        """1
        QA Cleared: Release QA Status = Cleared 并且 还没有创建对应的Submission Request 或者Submission Request Validation = Pending
        
        [TODO:问下 releaseQA 与 sub_req关系，好像是rel_qa依赖sub_rq]
        
        

        QA_STATUS = (
            ('P', 'Pending'),
            ('I', 'In Progress'),
            ('D', 'Cleared'),
            ('O', 'On Hold'),
            ('X', 'Cancelled')
        )
 
 
        VALIDATION = (
            ('P', 'Pending'),
            ('V', 'Valid'),
            ('I', 'Invalid'),
            ('C', 'Cancelled')
        )
        """
        out=[]
        for rel in ReleaseQAInfo.objects.filter(status='D',dev_qa__app__app_store=self.store,dev_qa__app__company=self.company): # .filter(Q(sub_info=None)|Q(sub_info__validation='P')):
            dev=rel.dev_qa
            version=dev_to_version(dev)
            out.append(version)
        return out
    
    def get_queued(self):
        """
        SUBMISSION_STATUS = (
        #    ('P', 'Preparing'),
            ('Q', 'Queue'),
            ('S', 'Submitted'),
            ('O', 'On Hold'),
            ('C', 'Cancelled'),
        )
        """
        out=[]
        for sub in SubInfo.objects.filter(status='Q',app__app_store=self.store,app__company=self.company):
            version=sub_to_version(sub)
            out.append(version)
        return out   
    
    def get_submitted(self):
        """ 
        Submitted --pending release
        
        Submitted:  Submission Request中, Submission Status=Submitted 并且Review Status=Pending Review
        
        SUBMISSION_STATUS = (

        ('Q', 'Queue'),
        ('S', 'Submitted'),
        ('O', 'On Hold'),
        ('C', 'Cancelled'),
    )

        
        SUBINFO_REVIEW_STATUS = (
        ('A', 'Rejected'),
        ('B', 'Pending'),
        ('C', 'Released'),
        )
        
        SUBINFO_REVIEW_STATUS = (
        ('A', 'Rejected'),
        ('B', 'Pending'),
        ('C', 'Released'),
        )

        """
        out=[]
        for sub in SubInfo.objects.filter(status='S',review_status='B',app__app_store=self.store,app__company=self.company):
            # if sub.app.app_store==self.store:
            version=sub_to_version(sub)
            out.append(version)
        return out    

    def get_released(self):
        """
        ToDo 添加日期限定。。。。。。
        """
        ps=PS(settings.PS_DOMAIN)
        sub_array=ps.get_released_sub()
        out=[]
        for sub in sub_array:
            if sub.app.app_store==self.store and sub.app.company==self.company:
                version=sub_to_version(sub)
                out.append(version)
        return out
    

 
def get_last_sat():
    day=datetime.now().date()
    while day.isoweekday()!=6:
        day-=timedelta(days=1)
    return day

 
class AppStore(Store):
    def __init__(self,user,company):
        super(AppStore,self).__init__(user,company)
        self.store='iTunes App Store'
        self.include.extend(['pending_release','rejected'])

    def get_pending_release(self):
        """
        Pending Release:   （PS上） Review Status = Pending Release
        """
        out=[]
        ps=PS(settings.PS_DOMAIN)
        rt=ps.get_pending_release_sub()
        for sub in rt:
            # sub=SubInfo.objects.get(request_id=rq_id)
            if sub.app.app_store==self.store and sub.app.company==self.company:
                version=sub_to_version(sub)
                out.append(version)

        return out
    
    def get_rejected(self):
        """
        Rejected: （PS上）Rejection 里面有关联的Issue并且 Status = Open
        """
        out=[]
        ps=PS(settings.PS_DOMAIN)
        rt=ps.get_rejected_sub()
        for sub in rt:
            # sub=SubInfo.objects.get(request_id=rq_id)
            # app=sub.app
            if sub.app.app_store==self.store and sub.app.company==self.company:
                version=sub_to_version(sub) # app.appversion_set.filter(code=sub.version)[0]
                out.append(version)
        return out
    
    def get_submitted(self):
        """ 
        apple: submitted- pending review
        
        Submitted:  Submission Request中, Submission Status=Submitted 并且Review Status=Pending Review
        
        SUBMISSION_STATUS = (

        ('Q', 'Queue'),
        ('S', 'Submitted'),
        ('O', 'On Hold'),
        ('C', 'Cancelled'),
    )

        
        SUBINFO_REVIEW_STATUS = (
        ('A', 'Rejected'),
        ('B', 'Pending'),
        ('C', 'Released'),
        )
        
        SUBINFO_REVIEW_STATUS = (
        ('A', 'Rejected'),
        ('B', 'Pending'),
        ('C', 'Released'),
        )

        """
        ps=PS(settings.PS_DOMAIN)
        sub_array=ps.get_pending_review_sub()
        out=[]
        for sub in sub_array:
            if sub.app.app_store==self.store and sub.status=='S' and sub.app.company==self.company:
                version=sub_to_version(sub)
                out.append(version)
        return out    
    

class GpStore(Store):
    def __init__(self,user,company):
        super(GpStore,self).__init__(user,company)
        self.store='Google Play'
   

class AmazonStore(AppStore):
    def __init__(self, user, company):
        super(AmazonStore,self).__init__(user,company)
        self.store='Amazon App Store'
        
    
def sub_to_version(sub):
    app=sub.app
    version=app.appversion_set.filter(code=sub.version)[0]
    return version

def dev_to_version(dev):
    version=dev.app.appversion_set.filter(code=dev.version)[0]
    return version

class PS(object):
    def __init__(self,url):
        self.url=url
    
    def get_released_sub(self):
        """
        ('RE', 'Released'),
        """
        try:
            startday=get_last_sat().strftime('%Y-%m-%d')
            rt=urllib2.urlopen(self.url+'/get_sub_from_review/?status=RE&release_date__gte=%s'%startday)
            return self.subs_id_2_sub( json.loads(rt.read()) )
        except urllib2.URLError as e:
            print(str(e))
            print('this may be caused by PS not running')
            return []
        
    def get_pending_review_sub(self):
        """
        review.status=pending
        """
        try:
            rt=urllib2.urlopen(self.url+'/get_sub_from_review/?status=PR')
            return self.subs_id_2_sub( json.loads(rt.read()) )
        except urllib2.URLError as e:
            print(str(e))
            print('this may be caused by PS not running')
            return []        
        
    def get_pending_release_sub(self):
        """
        从ps系统获取 ReviewStatus.status='PE' (Pending Release) 的ReviewStatus，然后返回与其相关的subinfo
        """
        try:
            rt=urllib2.urlopen(self.url+'/get_sub_from_review/?status=PE')
            return self.subs_id_2_sub( json.loads(rt.read()) )
        except urllib2.URLError as e:
            print(str(e))
            print('this may be caused by PS not running')
            return []
        
    def get_rejected_sub(self):
        """
        从ps系统获取 Rejection.status='O'的 Rejection，然后返回与其相关的subinfo
        'O'代表 'Open',
        """
        try:
            rt=urllib2.urlopen(self.url+'/get_sub_from_rej/?status=O')
            return self.subs_id_2_sub( json.loads(rt.read()) )
        except urllib2.URLError as e:
            print(str(e))
            print('this may be caused by PS not running')            
            return []
    
    def subs_id_2_sub(self,sub_id_array):
        out=[]
        for sub_id in sub_id_array:
            try:
                out.append( SubInfo.objects.get(request_id=sub_id) )
            except SubInfo.DoesNotExist as e:
                print(e)
        return out
            
        